feat(mail): HTML lint lib + Larksuite-native autofix + lark-mail skill#5
Open
bubbmon233 wants to merge 10 commits into
Open
feat(mail): HTML lint lib + Larksuite-native autofix + lark-mail skill#5bubbmon233 wants to merge 10 commits into
bubbmon233 wants to merge 10 commits into
Conversation
Add an HTML lint library + Larksuite-native autofix to lark-cli mail, plus the skills/lark-mail/ skill bundle (2 reference docs, 5 HTML templates, the +lint-html shortcut, and writing-path lint integration across all 6 compose shortcuts). Lint library (shortcuts/mail/lint/) - Error: drop dangerous tags (<script> / <iframe> / <form> / <input> / <link> / <object> / <embed>), on* event handlers, javascript: / vbscript: / file: URLs. - Warning + autofix: rewrite HTML4-era <font> / <center> / <marquee> / <blink>. - Larksuite-native autofix: rewrite <p> / <ul> / <ol> / <li> / <blockquote> / <a> to mail-editor native markup so AI can write the simplest HTML and still produce native-quality rendering. - Inline-style and URL-scheme allow-list filtering. - <style> block passthrough (server adds CSS scope class). +lint-html shortcut (preview / CI) Read-only HTML preview tool. Default envelope returns only cleaned_html; --show-lint-details adds full warnings[] / errors[]. --strict exits non- zero on any finding (CI gate). Writing-path lint in 6 compose shortcuts +send / +draft-create / +reply / +reply-all / +forward / +draft-edit body op all run lint before drafting: - lint_applied_count / original_blocked_count: always present. - lint_applied[] / original_blocked[]: only with --show-lint-details. - compose_hint: points AI consumers to the HTML writing guide. skills/lark-mail/ skill bundle 5 pre-rendered Larksuite-native HTML templates: weekly newsletter, personal weekly report, team weekly report, market research report, résumé. 2 reference docs: - references/lark-mail-html.md: writing rules + format primitives + template-usage flow. - references/lark-mail-lint-html.md: +lint-html usage + return-value contract + 9 worked examples. SKILL.md updates linking the new docs and templates. Sealed conventions - @user mention chip: id="at-user-N" is the only hard requirement; do not write data-user-id. - Highlight palette: 3 colors (pink milestones, yellow follow-ups, green completed); black text, no bold / padding / border-radius. - Brand color palette: main black, 3 levels of grey, Lark blue / deep blue, alert red, emergency orange, light pink / light grey backgrounds, border grey. - URL scheme allow-list: http(s): / mailto: / cid: / data:image/* only. - Inline-style + tag allow-lists. - Writing-style floor: subject <= 50 chars, decision-first, lists instead of mechanical numbering, emoji only as status tags. Tests - shortcuts/mail/lint/...: unit tests for every rule. - shortcuts/mail/mail_lint_html_test.go: +lint-html envelope contract. - shortcuts/mail/mail_lint_writepath_test.go: writing-path envelope contract. - 5 templates verified via +draft-create smoke test.
3 tasks
Move data["lint_applied_count"] / data["original_blocked_count"] assignments inside the showDetails branch in applyLintToEnvelope so all four lint fields enter and leave the envelope together. This restores the default 3-key envelope (compose_hint / draft_id / reference) for the compose-family shortcuts (+send / +reply / +reply-all / +forward / +draft-create / +draft-edit) and keeps the four lint fields behind --show-lint-details as the tech design intends. sprint: S2
Remove tip field from buildDraftSavedOutput's returned map and flip the test assertions in TestBuildDraftSavedOutputIncludesReferenceOnlyWhenPresent to require tip absence. The compose-family default envelope (+send / +reply / +reply-all / +forward) now stays within the 3-key contract (compose_hint / draft_id / reference) defined in tech-design v1 §4.1.5. hintSendDraft already writes the equivalent guidance to stderr, so no UX regression — the message reaches the user via the dedicated stderr hint channel instead of the structured stdout envelope. sprint: S3
This reverts commit fe001f2.
+draft-create now always attaches a fixed draft_edit_hint to its stdout envelope (alongside compose_hint + draft_id), guiding callers to edit the existing draft via +draft-edit --draft-id <id> instead of re-running +draft-create and producing duplicate drafts. The hint is single-target: only MailDraftCreate emits it; the other 5 compose shortcuts (+send, +reply, +reply-all, +forward, +draft-edit) keep their existing envelope shape unchanged. applyLintToEnvelope no longer writes lint_applied_count or original_blocked_count. Under --show-lint-details the envelope returns only the two Finding arrays (lint_applied[] / original_blocked[]) — callers needing a count compute it via len(arr). The change propagates to all 6 compose shortcuts via the shared helper. Tests, the shortcut flag description, and the lark-mail-html / lark-mail-lint-html reference docs are updated to match. sprint: S2
…tcut structs (PR 787 followup) The 4 compose shortcuts (+send, +reply, +reply-all, +forward) were missing the `HasFormat: true` field in their Shortcut struct literals, so cobra parse rejected `--format json` with `unknown flag: --format`. This blocked the JSON envelope output path (compose_hint / lint envelope) that the verify suite exercises. The fix mirrors the existing positive siblings in the same package (mail_draft_create.go:43, mail_draft_edit.go:29, mail_lint_html.go:43): add a single line `HasFormat: true,` between `AuthTypes:` and `Flags:` in each of the 4 Shortcut struct literals. No new manual --format flag entry is added; the framework auto-registers --format via runner.go when HasFormat == true. Refs: verification_report §3.1 (fail_code_bug for INT-CLI-Send-DefaultHidesStrip-01)
+draft-edit only accepted body edits via --patch-file (set_body op), causing "unknown flag: --body" when called the same way as +draft-create. This adds --body as a convenience flag that translates directly into a set_body patch op, making all mail compose shortcuts consistent. - Add --body flag to MailDraftEdit.Flags - In buildDraftEditPatch: if --body is set, prepend a set_body op; mutual-exclusion check prevents combining with --patch-file body ops - Update patch template notes to reflect the new --body shorthand - Existing lint pipeline (Execute loop over ops) already handles the new op: HTML is sanitized, envelope hides lint_applied/original_blocked by default unless --show-lint-details is passed Fixes: INT-CLI-DraftEdit-DefaultHidesStrip-01 and dependent cases
Bug 1: Template HTML <li> elements with class "temp-li bullet2" or "temp-li bullet3" were missing the "bullet1" class required by the STYLE_LIST_ITEM_NATIVE_INLINE_APPLIED lint rule, causing 18+ warnings in --strict mode for PersonalWeekly/TeamWeekly/Resume templates. research--market-report.html used native <li> elements which were fully converted to Feishu-native list format (ul/ol + li with all required class, data-* attrs, style props and text span wrapping). Bug 2: +send lacked --body-file flag, breaking the E2E workflow: +lint-html → save cleaned.html → +send --body-file ./cleaned.html Added --body-file flag (mutually exclusive with --body) that reads the HTML body from a file. Matches the pattern in +lint-html.
- Add class="not-doclink" to all 20 mention-chip <a id="at-user-N"> elements (fixes 20× STYLE_LINK_NATIVE_INLINE_APPLIED warnings in --strict mode) - Change class="temp-li number2" → "temp-li number1 number2" on the two <li data-start="a|b"> sub-items in 下周工作 nested ol (fixes 2× STYLE_LIST_ITEM_NATIVE_INLINE_APPLIED warnings) - Add start="1" to the outer wrapper <ol> of the nested weekly-next sub-list (fixes 1× STYLE_LIST_NATIVE_INLINE_APPLIED warning; ensureAttr saw start absent) All 23 warnings eliminated; +lint-html --strict should now exit 0.
9783a06 to
f4e4e5e
Compare
Replace 11 <p> tags with <div> elements (preserving inline styles) to eliminate STYLE_PARA_WRAPPER_REWRITTEN warnings. The lint engine rewrites <p> to Lark-native double-wrapped div paragraphs and emits a warning for each; using <div> directly avoids the rewrite. Also add class="not-doclink" + native link inline styles to 3 bare <a> tags in the PR-reference section, eliminating STYLE_LINK_NATIVE_INLINE_APPLIED warnings. Verified with lint.Run() directly: blocked=0 applied=0 (0 findings). All 5 templates now pass +lint-html --strict with 0 findings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an HTML lint library + Larksuite-native autofix to
lark-cli mail, plus theskills/lark-mail/skill bundle (2 reference docs, 5 HTML templates, the+lint-htmlshortcut, and writing-path lint integration across all 6 compose shortcuts).What's in this PR
1. Lint library (
shortcuts/mail/lint/)3-tier rule set:
<script>/<iframe>/<form>/<input>/<link>/<object>/<embed>),on*event handlers, andjavascript:/vbscript:/file:URLs.<font>/<center>/<marquee>/<blink>).<p>/<ul>/<ol>/<li>/<blockquote>/<a>to mail-editor native markup so AI can write the simplest HTML and still produce native-quality rendering.<style>block passthrough (server adds CSS scope class).2.
+lint-htmlshortcut (preview / CI)Read-only HTML preview tool. Default envelope returns only
cleaned_html;--show-lint-detailsadds fullwarnings[]/errors[].--strictexits non-zero on any finding (CI gate).3. Writing-path lint in the 6 compose shortcuts
+send/+draft-create/+reply/+reply-all/+forward/+draft-editbody op all run lint before drafting:lint_applied_count/original_blocked_count— always present.lint_applied[]/original_blocked[]— only with--show-lint-details.compose_hint— points AI consumers to the HTML writing guide.4.
skills/lark-mail/skill bundlereferences/lark-mail-html.md— writing rules + format primitives + template-usage flow.references/lark-mail-lint-html.md—+lint-htmlusage + return-value contract + 9 examples.SKILL.mdupdates linking the new docs and templates.5. Sealed conventions
Fixed writing conventions enforced by the lint library, the Larksuite mail-editor data model, or the upstream service-side sanitiser.
id="at-user-N"is the only hard requirement; do not writedata-user-id.http(s):/mailto:/cid:/data:image/*only.<p>/<div>/<span>/<a>/<img>/<table>(with<thead>/<tbody>/<tfoot>/<tr>/<td>/<th>/<caption>/<colgroup>/<col>) /<ul>/<ol>/<li>/<blockquote>/<h1>-<h6>/<b>/<i>/<em>/<strong>/<u>/<s>/<sub>/<sup>/<pre>/<code>/<style>.Tests
shortcuts/mail/lint/...— unit tests for every rule.shortcuts/mail/mail_lint_html_test.go—+lint-htmlenvelope contract.shortcuts/mail/mail_lint_writepath_test.go— writing-path envelope contract.+draft-createsmoke test.Test plan
go test ./shortcuts/mail/lint/... ./shortcuts/mail/...+draft-createsmoke--show-lint-detailsenvelope verified for both+lint-htmland+draft-create